XPath Basics
XPath stands for XML Path Language. In Selenium WebDriver, XPath is a powerful locator strategy used to identify and interact with web elements on an HTML page. XPath allows testers to locate elements using tags, attributes, text, positions, and relationships between elements.
XPath is especially useful when a web element does not have a unique ID, Name, or other simple locator. It can also be used to locate elements in complex DOM structures and dynamic web applications.
For Selenium automation learning and practical testing concepts, you can explore the Selenium Training Course and register for the Selenium Course Demo.
1. What is XPath?
XPath is a query language used to navigate through the structure of an XML or HTML document. Selenium uses XPath expressions to identify specific elements in the Document Object Model (DOM).
For example, consider the following HTML:
<input id="username" type="text">
The element can be identified using the following XPath:
//input[@id='username']
The XPath tells Selenium to find an input element whose id attribute has the value username.
2. Why is XPath Important in Selenium?
XPath is important because web applications can contain many elements with similar tags, classes, or attributes. XPath provides a flexible way to identify the exact element required by the automation script.
- It can locate elements using attributes.
- It can locate elements using visible text.
- It can locate elements using partial attribute values.
- It can locate elements using parent-child relationships.
- It can locate elements using sibling relationships.
- It can handle complex DOM structures.
- It can help locate dynamic web elements.
- It can combine multiple conditions.
- It can identify specific elements inside tables and forms.
- It is useful when simpler locators are not sufficient.
3. XPath and Selenium WebDriver
Selenium WebDriver interacts with web pages through the DOM created by the browser. XPath provides a way to search this DOM and identify the required WebElement.
Web Page
↓
HTML
↓
DOM Tree
↓
XPath Expression
↓
Selenium WebDriver
↓
WebElement
↓
Click / Type / Read / Validate
For example:
WebElement username = driver.findElement(By.xpath("//input[@id='username']"));
username.sendKeys("admin");
4. Basic XPath Syntax
The basic XPath syntax is:
//tagname[@attribute='value']
Here:
- // means search for the element anywhere in the document.
- tagname represents the HTML tag.
- @attribute represents an HTML attribute.
- value represents the value of that attribute.
Example:
//input[@id='username']
This expression searches for an input element whose id is username.
5. Understanding the // Symbol
The double slash is one of the most commonly used parts of a relative XPath.
//input
This means Selenium should search for input elements anywhere in the document rather than starting from a specific root path.
Another example:
//button
This searches for button elements anywhere in the DOM.
6. Understanding the @ Symbol
The @ symbol is used to reference an attribute in XPath.
Example HTML:
<input id="username" name="user" type="text">
XPath using id:
//input[@id='username']
XPath using name:
//input[@name='user']
XPath using type:
//input[@type='text']
7. Relative XPath
Relative XPath starts from a point in the DOM where the required element can be found rather than specifying the complete path from the root.
//input[@id='username']
Relative XPath is commonly used in Selenium because it is generally shorter, easier to read, and less dependent on the complete page hierarchy.
8. Absolute XPath
Absolute XPath starts from the root of the HTML document and specifies the complete path to an element.
Example:
/html/body/div/form/input
Absolute XPath can be affected by changes in the DOM hierarchy. If a new div or another element is inserted into the path, the XPath may no longer identify the intended element.
9. Absolute XPath vs Relative XPath
| Feature | Absolute XPath | Relative XPath |
| Starting point | Root element | Matching element or location in DOM |
| Syntax | Usually starts with / | Usually starts with // |
| Length | Usually longer | Usually shorter |
| Maintainability | Lower | Higher |
| Flexibility | Lower | Higher |
| Dynamic pages | Can be fragile | Generally more flexible |
10. XPath Using ID
If an element has a unique and stable ID, it can be used to create an XPath.
HTML:
<input id="username" type="text">
XPath:
//input[@id='username']
Selenium:
driver.findElement(By.xpath("//input[@id='username']")).sendKeys("admin");
11. XPath Using Name
The name attribute can be used when it provides a useful way to uniquely identify an element.
<input name="email" type="text">
XPath:
//input[@name='email']
Selenium:
driver.findElement(By.xpath("//input[@name='email']")).sendKeys("[email protected]");
12. XPath Using Class
The class attribute can be used in an XPath expression.
<button class="login-button">Login</button>
XPath:
//button[@class='login-button']
When an element contains multiple class names, matching the complete class attribute may not always be suitable.
13. XPath Using Tag Name
A tag name can be used when it uniquely identifies the required element or when it is combined with another condition.
//button
If many button elements exist, the XPath can be made more specific using attributes or text.
//button[@id='login']
14. XPath Using Multiple Attributes
Multiple attributes can be combined using the and operator.
//input[@type='text' and @name='username']
This XPath identifies an input element whose type is text and whose name is username.
15. XPath Using OR Condition
The or operator allows an XPath to match an element when at least one condition is satisfied.
//input[@id='username' or @name='username']
This can be useful when an element may be identified using either of two possible attributes.
16. XPath Using Text
XPath can locate an element based on its visible text using the text() function.
HTML:
<button>Login</button>
XPath:
//button[text()='Login']
Selenium:
driver.findElement(By.xpath("//button[text()='Login']")).click();
17. XPath Using contains()
The contains() function is useful when only part of an attribute value or text is known.
//input[contains(@id,'user')]
For text:
//button[contains(text(),'Login')]
For example, the second XPath can match button text containing the word Login.
18. XPath Using starts-with()
The starts-with() function identifies elements where an attribute value begins with a specified string.
//input[starts-with(@id,'user')]
This can be useful when part of an ID remains stable while another part changes dynamically.
19. XPath Using normalize-space()
normalize-space() is useful when text contains additional spaces or line breaks.
//button[normalize-space()='Login']
It can help match text after unnecessary whitespace has been normalized.
20. XPath Using and
The and operator requires all specified conditions to be true.
//input[@type='text' and @name='username']
Both the type and name conditions must match.
21. XPath Using not()
The not() function can be used to exclude elements that satisfy a specific condition.
//button[not(@disabled)]
This XPath identifies buttons that do not have the disabled attribute.
22. XPath Index
When multiple elements match an XPath expression, an index can be used to select a particular occurrence.
(//button)[1]
This selects the first matching button.
(//button)[2]
This selects the second matching button.
Indexes should be used carefully because the order of elements can change when the page structure changes.
23. XPath Using last()
The last() function selects the last element from the matching collection.
(//button)[last()]
This expression selects the last matching button.
24. XPath Using position()
The position() function can be used to identify an element based on its position.
//button[position()=2]
This selects the second matching button.
25. XPath Parent Relationship
XPath can navigate from a child element to its parent element.
//input[@id='username']/parent::div
This searches for the div that is the parent of the username input.
26. XPath Child Relationship
The child relationship can be used to identify direct children of an element.
//div[@id='login']/child::input
Short form:
//div[@id='login']/input
27. XPath Descendant Relationship
The descendant relationship is useful when an element can appear at any nested level below another element.
//div[@id='login']//input
This searches for input elements located anywhere inside the login div.
28. XPath Ancestor Relationship
The ancestor axis allows XPath to move from an element toward its parent and higher-level elements.
//input[@name='username']/ancestor::form
This identifies a form containing the username input.
29. XPath Using Following-Sibling
The following-sibling axis identifies sibling elements that appear after the current element.
//label[text()='Username']/following-sibling::input
This can locate an input field that follows a Username label.
30. XPath Using Preceding-Sibling
The preceding-sibling axis identifies sibling elements that appear before the current element.
//input[@id='username']/preceding-sibling::label
This can locate a label that appears before the username input.
31. XPath for Links
Links can be located using their text, partial text, href, or other attributes.
//a[text()='Home']
Partial text:
//a[contains(text(),'Home')]
Using href:
//a[@href='/home']
32. XPath for Buttons
Buttons can be located using their ID, text, class, type, or other attributes.
//button[@id='login']
//button[text()='Login']
//button[contains(text(),'Login')]
33. XPath for Input Fields
Input fields are frequently located using their type, ID, name, placeholder, or other attributes.
//input[@type='text']
//input[@placeholder='Enter Username']
//input[@name='username']
34. XPath for Checkboxes
Checkboxes are commonly represented using an input element with type checkbox.
//input[@type='checkbox']
A more specific XPath can be created using another attribute.
//input[@type='checkbox' and @name='terms']
Selenium example:
driver.findElement(By.xpath("//input[@type='checkbox' and @name='terms']")).click();
35. XPath for Radio Buttons
Radio buttons can be identified using the type attribute and another identifying attribute.
//input[@type='radio' and @value='male']
Selenium example:
driver.findElement(By.xpath("//input[@type='radio' and @value='male']")).click();
36. XPath for Dropdowns
A select element can be located using XPath and then handled using Selenium's Select class.
//select[@id='country']
Java Selenium example:
WebElement country = driver.findElement(By.xpath("//select[@id='country']"));
Select select = new Select(country);
select.selectByVisibleText("India");
37. XPath for Images
Images can be identified using the img tag and attributes such as alt or src.
//img[@alt='Company Logo']
Partial alt text:
//img[contains(@alt,'Logo')]
38. XPath for Tables
XPath is very useful for locating table rows, cells, columns, and action buttons.
//table[@id='employees']//tr
To locate table cells:
//table[@id='employees']//tr/td
39. XPath for a Specific Table Row
Suppose an employee table contains a row with the employee name John.
//table[@id='employees']//tr[td[text()='John']]
This expression searches for a table row containing a cell whose text is John.
40. XPath for a Button Inside a Table Row
XPath can locate an action button inside the row belonging to a specific record.
//tr[td[text()='John']]//button[text()='Edit']
This is useful for applications containing Edit, Delete, View, or other actions for individual records.
41. XPath for Dynamic IDs
Modern web applications can generate dynamic IDs. For example:
<input id="user_12345" type="text">
A complete ID-based XPath may be fragile:
//input[@id='user_12345']
If user_ is stable while the number changes, contains() can be used:
//input[contains(@id,'user_')]
42. XPath for Dynamic Classes
Classes can also contain dynamic values. If a stable part of the class is available, contains() can be useful.
//button[contains(@class,'login')]
The locator should be tested to ensure that it identifies the intended element uniquely.
43. XPath with Multiple Conditions
Multiple conditions can be combined to create a more specific XPath.
//input[@type='text' and @name='email' and contains(@class,'form-control')]
Using several stable conditions can reduce the possibility of selecting the wrong element.
44. XPath with Data Attributes
Modern web applications may contain custom attributes such as data-testid, data-id, or data-name.
Example:
<button data-testid="login-button">Login</button>
XPath:
//button[@data-testid='login-button']
45. XPath with aria-label
Accessibility attributes can sometimes provide useful element identification.
Example:
<button aria-label="Search">Search</button>
XPath:
//button[@aria-label='Search']
46. XPath with Placeholder
The placeholder attribute can be used when it provides a stable identifying value.
<input placeholder="Enter Username">
XPath:
//input[@placeholder='Enter Username']
47. XPath with Value Attribute
The value attribute can be used when it provides a useful identifying value.
<input type="submit" value="Login">
XPath:
//input[@value='Login']
48. XPath for Form Elements
XPath can locate elements relative to a specific form.
//form[@id='loginForm']//input[@name='username']
This ensures that the username input is searched inside the specified login form.
49. XPath for Nested Elements
Web pages frequently contain deeply nested HTML elements. XPath can navigate through these nested structures.
//div[@class='login-container']//form//input[@name='username']
The double slash allows Selenium to find the input at any descendant level within the specified container.
50. XPath Using Text and Attribute Together
Text and attributes can be combined for a more specific locator.
//button[@type='submit' and text()='Login']
This identifies a submit button whose visible text is Login.
51. XPath Using contains() with Attribute and Text
contains() can be combined with multiple conditions.
//button[contains(@class,'submit') and contains(text(),'Submit')]
This can identify a button based on both its class and visible text.
52. XPath Using Parent Based on Child
An element can be located by first identifying a child and then moving to its parent.
//input[@name='username']/parent::div
This approach is useful when the parent does not have a reliable attribute but the child does.
53. XPath Using Ancestor Based on Child
An ancestor can be located when a known child element exists inside a larger container.
//input[@name='username']/ancestor::form
This can identify the form containing the username field.
54. XPath Using Sibling Relationship
Sibling relationships are useful when elements are positioned next to each other.
//label[text()='Email']/following-sibling::input
This expression can locate the input associated with the Email label when the elements have the required sibling structure.
55. XPath Using findElement()
Selenium uses By.xpath() with findElement() to locate a single matching element.
WebElement username = driver.findElement(By.xpath("//input[@id='username']"));
The returned WebElement can then be used to perform actions.
username.sendKeys("admin");
56. XPath Using findElements()
findElements() can be used when multiple elements are expected to match an XPath.
List<WebElement> buttons = driver.findElements(By.xpath("//button"));
System.out.println(buttons.size());
This is useful when the automation script needs to count or iterate through multiple matching elements.
57. XPath with Explicit Wait
Dynamic web applications may load elements after the initial page load. XPath can be combined with explicit waits to wait for an element condition.
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement login = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//button[@id='login']")));
login.click();
58. XPath in a Login Test
Consider a login page containing username, password, and login button.
<input id="username" type="text">
<input id="password" type="password">
<button id="login">Login</button>
XPath expressions:
//input[@id='username']
//input[@id='password']
//button[@id='login']
Selenium code:
driver.findElement(By.xpath("//input[@id='username']")).sendKeys("admin");
driver.findElement(By.xpath("//input[@id='password']")).sendKeys("password123");
driver.findElement(By.xpath("//button[@id='login']")).click();
59. Complete XPath Selenium Example
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class XPathBasics {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
driver.get("https://example.com");
WebElement username = driver.findElement(By.xpath("//input[@id='username']"));
username.sendKeys("admin");
WebElement password = driver.findElement(By.xpath("//input[@id='password']"));
password.sendKeys("password123");
WebElement loginButton = driver.findElement(By.xpath("//button[@id='login']"));
loginButton.click();
driver.quit();
}
}
60. XPath in Page Object Model
In the Page Object Model, XPath locators can be stored as private By objects inside page classes.
public class LoginPage {
private WebDriver driver;
private By username = By.xpath("//input[@id='username']");
private By password = By.xpath("//input[@id='password']");
private By loginButton = By.xpath("//button[@id='login']");
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public void login(String user, String pass) {
driver.findElement(username).sendKeys(user);
driver.findElement(password).sendKeys(pass);
driver.findElement(loginButton).click();
}
}
61. XPath for E-Commerce Applications
XPath is frequently useful when multiple products have similar structures and each product has its own action button.
Example:
<div class="product">
<h3>Laptop</h3>
<button>Add to Cart</button>
</div>
XPath:
//div[h3[text()='Laptop']]//button[text()='Add to Cart']
This identifies the Add to Cart button associated with the Laptop product.
62. XPath for Validation Messages
XPath can be used to locate error and validation messages displayed on forms.
//span[contains(@class,'error')]
For a specific message:
//span[normalize-space()='Username is required']
63. XPath for Navigation Menus
Navigation links can be located using their visible text or attributes.
//nav//a[text()='Home']
Partial text:
//nav//a[contains(text(),'Products')]
64. XPath for Modal Windows
XPath can locate elements inside modal dialogs.
//div[contains(@class,'modal')]//button[text()='Close']
This identifies a Close button inside a modal container.
65. XPath for Enabled and Disabled Elements
An element containing the disabled attribute can be located using XPath.
//button[@disabled]
To locate buttons without the disabled attribute:
//button[not(@disabled)]
66. XPath for Dynamic Web Elements
Dynamic web elements may have changing IDs, classes, generated text, or changing positions. XPath functions and relationships can help create locators that depend on stable portions of the DOM.
//button[contains(@class,'submit') and normalize-space()='Submit']
The locator should always be validated against the actual application DOM to make sure it identifies the intended element.
67. Testing XPath in Browser Developer Tools
- Open the web application.
- Right-click the required element.
- Select Inspect.
- Find the element in the Elements panel.
- Study its tag and attributes.
- Identify stable attributes.
- Create a relative XPath.
- Test the XPath in developer tools.
- Use the validated XPath in Selenium.
68. Testing XPath in Chrome Console
Chrome DevTools provides the $x() function for evaluating XPath expressions.
$x("//input[@id='username']")
If the expression matches an element, the browser can display the matching node in the console.
69. Common XPath Mistakes
- Using very long absolute XPath expressions.
- Depending on dynamic IDs without checking their stability.
- Using unnecessary indexes.
- Using changing text unnecessarily.
- Ignoring parent-child relationships.
- Creating XPath without checking whether it is unique.
- Using class values that are not stable.
- Not testing the XPath before using it in automation.
- Using complex XPath when a simple attribute-based XPath is available.
70. XPath Best Practices
- Prefer relative XPath for normal Selenium automation.
- Use stable and meaningful attributes.
- Prefer unique IDs when they are reliable.
- Use multiple attributes when necessary.
- Use contains() for suitable dynamic values.
- Use normalize-space() when whitespace affects text matching.
- Use relationships when direct attributes are unavailable.
- Avoid unnecessary indexes.
- Avoid unnecessarily long XPath expressions.
- Validate XPath in browser developer tools.
- Keep XPath readable and maintainable.
- Use explicit waits for dynamically loaded elements when required.
71. XPath Quick Reference
| Purpose | XPath |
| ID | //input[@id='username'] |
| Name | //input[@name='username'] |
| Class | //button[@class='login-button'] |
| Text | //button[text()='Login'] |
| Contains Text | //button[contains(text(),'Login')] |
| Contains Attribute | //input[contains(@id,'user')] |
| Starts With | //input[starts-with(@id,'user')] |
| Multiple Conditions | //input[@type='text' and @name='username'] |
| First Match | (//button)[1] |
| Last Match | (//button)[last()] |
| Parent | //input/parent::div |
| Child | //div/child::input |
| Descendant | //div//input |
| Ancestor | //input/ancestor::form |
| Following Sibling | //label/following-sibling::input |
| Preceding Sibling | //input/preceding-sibling::label |
| Normalized Text | //button[normalize-space()='Login'] |
| Not Disabled | //button[not(@disabled)] |
72. XPath vs ID Locator
| Feature | XPath | ID |
| Attribute based | Yes | Yes |
| Text based | Yes | No |
| Parent-child navigation | Yes | No |
| Sibling navigation | Yes | No |
| Complex conditions | Yes | No |
| Syntax complexity | Higher | Lower |
73. XPath vs CSS Selector
| Feature | XPath | CSS Selector |
| Attribute selection | Supported | Supported |
| Text matching | Supported | Not directly equivalent |
| Parent navigation | Supported | More limited depending on selector |
| Sibling selection | Supported | Supported |
| Complex relationships | Highly flexible | Flexible |
| Readability | Can become complex | Often compact |
74. When Should You Use XPath?
- When an element does not have a unique ID.
- When an element needs to be identified using visible text.
- When multiple attributes must be combined.
- When the element has dynamic attributes.
- When an element needs to be located relative to another element.
- When a specific table row needs to be identified.
- When a button needs to be located inside a particular record.
- When elements are deeply nested.
- When parent, child, ancestor, or sibling relationships are useful.
75. XPath Interview Questions
1. What is XPath?
XPath is a language used to navigate HTML and XML structures and identify elements based on their properties and relationships.
2. Why is XPath used in Selenium?
XPath provides a flexible way to locate web elements when simpler locators such as ID or Name are unavailable or insufficient.
3. What is the difference between absolute and relative XPath?
Absolute XPath starts from the root of the document and specifies the complete path. Relative XPath searches for an element using a relative expression and is commonly used in Selenium.
4. What does // mean in XPath?
The // expression searches for matching elements anywhere below the current context.
5. What does @ mean in XPath?
The @ symbol is used to reference an attribute.
6. How do you locate an element by text?
//button[text()='Login']
7. How do you use contains()?
//input[contains(@id,'user')]
8. How do you use starts-with()?
//input[starts-with(@id,'user')]
9. How do you select the first matching element?
(//button)[1]
10. How do you select the last matching element?
(//button)[last()]
11. How do you locate an element using multiple attributes?
//input[@type='text' and @name='username']
12. How do you locate a button inside a particular table row?
//tr[td[text()='John']]//button[text()='Edit']
76. XPath Practice Exercise
Create a login page containing a username field, password field, Login button, Forgot Password link, and validation message. Practice creating XPath expressions using ID, Name, Text, contains(), starts-with(), normalize-space(), parent-child relationships, and sibling relationships.
Example HTML:
<form id="loginForm">
<label>Username</label>
<input id="username" name="username" type="text">
<label>Password</label>
<input id="password" name="password" type="password">
<button id="login" type="submit">Login</button>
<a href="/forgot-password">Forgot Password?</a>
</form>
Possible XPath expressions:
//input[@id='username']
//input[@name='password']
//button[@id='login']
//button[text()='Login']
//a[text()='Forgot Password?']
//form[@id='loginForm']//input
//form[@id='loginForm']//button
77. XPath Learning Checklist
- Understand the DOM structure.
- Understand XPath syntax.
- Understand absolute XPath.
- Understand relative XPath.
- Practice XPath using ID.
- Practice XPath using Name.
- Practice XPath using Class.
- Practice XPath using Text.
- Practice contains().
- Practice starts-with().
- Practice normalize-space().
- Practice and and or operators.
- Practice not().
- Practice indexing.
- Practice position().
- Practice last().
- Practice parent and child relationships.
- Practice descendant and ancestor relationships.
- Practice sibling relationships.
- Practice XPath with dynamic elements.
- Practice XPath with tables.
- Practice XPath with forms.
- Validate XPath using browser developer tools.
- Use XPath with Selenium WebDriver.
- Practice XPath in real automation projects.
78. Real-World XPath Automation Flow
Open Application
↓
Inspect Web Element
↓
Understand DOM
↓
Identify Stable Attribute
↓
Create XPath
↓
Test XPath
↓
Use By.xpath()
↓
Find WebElement
↓
Perform Action
↓
Validate Result
79. Common XPath Locator Examples
//input[@id='username']
//input[@name='email']
//input[@type='password']
//button[@id='login']
//button[text()='Login']
//button[contains(text(),'Login')]
//a[text()='Home']
//a[contains(text(),'Product')]
//input[contains(@id,'user')]
//input[starts-with(@id,'user')]
//select[@id='country']
//input[@type='checkbox']
//input[@type='radio']
//div[@id='login']//input
//form[@id='loginForm']//button
80. Conclusion
XPath is one of the most important locator strategies in Selenium WebDriver. It provides flexible ways to identify elements using attributes, text, positions, and relationships within the DOM. Understanding XPath basics helps automation testers work with simple forms as well as complex and dynamic web applications.
A strong understanding of relative XPath, attributes, text functions, contains(), starts-with(), normalize-space(), indexes, parent-child relationships, sibling relationships, and dynamic element handling provides a strong foundation for advanced Selenium automation.
For further Selenium automation learning and practical testing concepts, visit the JustAcademy Selenium Training Course and explore the Selenium Training Demo Registration.